﻿using System;
using System.Runtime.InteropServices;

namespace FrontDisplay.NativeMethods
{
    public static partial class WinApi
    {
        public class MouseMessages
        {
            public const int WM_MOUSEACTIVATE = 0x0021;
            public const int WM_MOUSEFIRST = 0x0200;
            public const int WM_MOUSEHOVER = 0x02A1;
            public const int WM_MOUSELAST = 0x020D;
            public const int WM_MOUSELEAVE = 0x02A3;
            public const int WM_MOUSEMOVE = 0x0200;
            public const int WM_MOUSEWHEEL = 0x020A;
            public const int WM_MOUSEHWHEEL = 0x020E; 

            public const int WM_LBUTTONDOWN = 0x0201;
            public const int WM_LBUTTONUP = 0x0202;
            public const int WM_LBUTTONDBLCLK = 0x0203;
            public const int WM_RBUTTONDOWN = 0x0204;
            public const int WM_RBUTTONUP = 0x0205;
        }

        public const int GWL_EXSTYLE = (-20);
        public const int WS_EX_TOOLWINDOW = 0x80;
        public const int WS_EX_APPWINDOW = 0x40000;
        public const int WM_USER = 0x0400;
        public const int WM_COPYDATA = 0x004A;
        public const int MK_LBUTTON = 0x0001;
        public const uint WM_HOTKEY = 0x312;
        public const uint MOD_ALT = 0x1;
        public const uint MOD_CONTROL = 0x2;
        public const uint MOD_SHIFT = 0x4;
        public const uint MOD_WIN = 0x8;
        public const uint ERROR_HOTKEY_ALREADY_REGISTERED = 1409;

        [DllImport("user32.dll", SetLastError = true)]
        public static extern int RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, int vk);

        [DllImport("user32.dll", SetLastError = true)]
        public static extern int UnregisterHotKey(IntPtr hWnd, int id);

        [DllImport("user32", CharSet = CharSet.Auto)]
        public static extern int GetWindowLong(IntPtr hWnd, int nIndex);

        [DllImport("user32", CharSet = CharSet.Auto)]
        public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
        public static extern IntPtr SendMessage(IntPtr hWnd, Int32 Msg, IntPtr wParam, IntPtr lParam);

        [DllImport("user32.dll")]
        public static extern IntPtr RealChildWindowFromPoint(IntPtr parent, Point point);

        [DllImport("user32.dll")]
        public static extern IntPtr GetMenu(IntPtr hwnd);

        [DllImport("user32.dll")]
        static extern bool ClientToScreen(IntPtr hwnd, ref Point point);

        public static Point ClientToScreen(IntPtr hwnd, Point clientPoint)
        {
            Point localCopy = new Point(clientPoint);

            return ClientToScreen(hwnd, ref localCopy) ? localCopy : new Point();
        }

        [DllImport("user32.dll")]
        static extern bool ScreenToClient(IntPtr hwnd, ref Point point);

        public static Point ScreenToClient(IntPtr hwnd, Point screenPoint)
        {
            Point localCopy = new Point(screenPoint);

            return ScreenToClient(hwnd, ref localCopy) ? localCopy : new Point();
        }

        [return: MarshalAs(UnmanagedType.Bool)]
        [DllImport("user32.dll", SetLastError = false)]
        public static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

        public static IntPtr MakeLParam(int LoWord, int HiWord)
        {
            return new IntPtr((HiWord << 16) | (LoWord & 0xffff));
        }

        [DllImport("kernel32.dll", SetLastError = true)]
        public static extern IntPtr LocalAlloc(int flag, int size);

        [DllImport("kernel32.dll", SetLastError = true)]
        public static extern IntPtr LocalFree(IntPtr p);

        [DllImport("user32.dll", SetLastError = true)]
        public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

        /// <summary>
        /// The SendMessage API
        /// </summary>
        /// <param name="hWnd">handle to the required window</param>
        /// <param name="Msg">the system/Custom message to send</param>
        /// <param name="wParam">first message parameter</param>
        /// <param name="lParam">second message parameter</param>
        /// <returns></returns>
        [DllImport("user32.dll")]
        public static extern int SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, ref CopyDataStruct lParam);

        public static bool SendTextToWindow(IntPtr targetHWnd, string text)
        {
            CopyDataStruct cds = new CopyDataStruct();
            try
            {
                cds.cbData = (text.Length + 1) * 2;
                cds.lpData = LocalAlloc(0x40, cds.cbData);
                Marshal.Copy(text.ToCharArray(), 0, cds.lpData, text.Length);
                cds.dwData = (IntPtr)1;
                SendMessage(targetHWnd, WM_COPYDATA, IntPtr.Zero, ref cds);
            }
            finally
            {
                cds.Dispose();
            }

            return true;
        } 


        //[StructLayout(LayoutKind.Sequential)]
        //struct Rect
        //{
        //    public int left;
        //    public int top;
        //    public int right;
        //    public int bottom;
        //}

        //[StructLayout(LayoutKind.Sequential)]
        //struct MonitorInfo
        //{
        //    public uint size;
        //    public Rect monitor;
        //    public Rect work;
        //    public uint flags;
        //}

        //private static List<MonitorInfo> _monitors = new List<MonitorInfo>();

        //delegate bool MonitorEnumDelegate(IntPtr hMonitor, IntPtr hdcMonitor, ref Rect lprcMonitor, IntPtr dwData);

        //[DllImport("user32.dll")]
        //static extern bool EnumDisplayMonitors(IntPtr hdc, IntPtr lprcClip, MonitorEnumDelegate lpfnEnum, IntPtr dwData);

        //[DllImport("user32.dll")]
        //static extern bool GetMonitorInfo(IntPtr hmon, ref MonitorInfo mi);
        //static bool MonitorEnum(IntPtr hMonitor, IntPtr hdcMonitor, ref Rect lprcMonitor, IntPtr dwData)
        //{
        //    MonitorInfo mi = new MonitorInfo();
        //    mi.size = (uint)Marshal.SizeOf(mi);
        //    bool success = GetMonitorInfo(hMonitor, ref mi);

        //    if (success)
        //    {
        //        _monitors.Add(mi);
        //    }
        //    return true;
        //}

        //_monitors.Clear();
        //MonitorEnumDelegate med = MonitorEnum;
        //EnumDisplayMonitors(IntPtr.Zero, IntPtr.Zero, med, IntPtr.Zero);
    }
}
